package OrderedCoverPackage;

import OLDSTUFF.DataSetPackage.DataSetException;
import Estimator.OLDSTUFF_EstimatorExp;
import OLDSTUFF.HierarchyPackage.HClass;
import OLDSTUFF.HierarchyPackage.HierarchyException;
import OLDSTUFF.HierarchyPackage.ProductHierarchy.ProductHClass;
import OLDSTUFF.HierarchyPackage.ProductHierarchy.ProductHierarchy;
import OLDSTUFF.HierarchyPackage.AffixHierarchies.SuffixHClass;
import OLDSTUFF.HierarchyPackage.AffixHierarchies.SuffixHierarchy;
import java.io.IOException;

import java.util.List;

/**
 * Helper class to use cover trained on suffix-classes as simple n-gramm estimator.
 * @author Martin Haulrich
 */
public class NSuffixOCEstimator extends OrderedCoverEstimator {

    /**
     * What is N in n-gram
     */
    final int N;

    /**
     * The hierarchy that is the base of the cover.
     */
    final ProductHierarchy phier;

    /**
     * The suffix hierarchies in the product hierarchy.
     */
    final SuffixHierarchy[] sufhiers;

    /**
     * @TODO hier and prior seems redundant as these should be accesible from the cover.
     */
    /**
     * Create ned estimator based on a trained cover.
     * @param cover Cover that has been trained on ProductHierarchy of SuffixHierarchies.
     * @param hier The product hiearchy the cover is based on.
     * @param prior The prior used in the training.
     * @throws HierarchyPackage.HierarchyException
     */
    public NSuffixOCEstimator(BaseHPM cover, ProductHierarchy hier, OLDSTUFF_EstimatorExp prior) throws HierarchyException {
        super(cover, hier, prior);
        N = hier.getHierarchies().length;
        phier = hier;
        sufhiers = new SuffixHierarchy[N];
        for (int i = 0; i < N; i++) {
            sufhiers[i] = (SuffixHierarchy) phier.getHierarchies()[i];
        }
    }

    /**
     * Load estimator from file.
     * @param fn Filename of estimator.
     * @param hier The product hiearchy the cover is based on.
     * @param prior The prior used in the training.
     * @throws HierarchyPackage.HierarchyException
     * @throws java.io.IOException
     */
    public NSuffixOCEstimator(String fn, ProductHierarchy hier, OLDSTUFF_EstimatorExp prior) throws HierarchyException, IOException {
        super(fn, hier, prior);
        N = hier.getHierarchies().length;
        phier = hier;
        sufhiers = new SuffixHierarchy[N];
        for (int i = 0; i < N; i++) {
            sufhiers[i] = (SuffixHierarchy) phier.getHierarchies()[i];
        }
    }

    /**
     * Get conditional or unconditional estimate of ngram.
     * @param ngram ngram to get estimate for.
     * @param condition Set true if it should be a condiational estimate.
     * @return The estimate of the ngram.
     * @throws DataSetPackage.DataSetException
     * @throws HierarchyPackage.HierarchyException
     */
    private double getEstim(List<String> ngram, boolean condition) throws DataSetException, HierarchyException {
        if (ngram.size() > N) {
            System.err.println("This is only a " + N + "-gram estimator");
            return Double.NaN;
        }

        HClass[] classes = new HClass[N];
        for (int i = 0; i < N; i++) {
            classes[i] = new SuffixHClass(sufhiers[i], ngram.get(i));
        }

        ProductHClass pc = new ProductHClass(phier, classes);
        double cond = 0;
        if (condition) {
            cond = getConditioningProb(pc);
        }

        return classAsDataPointEstimate(pc) - cond;
    }

    /**
     * Get conditional estimate of ngram.
     * @param ngram ngram to get estimate for.
     * @return The estimate of the ngram.
     * @throws DataSetPackage.DataSetException
     * @throws HierarchyPackage.HierarchyException
     */
    public double getEstimate(List<String> ngram) throws DataSetException, HierarchyException {

        return getEstim(ngram, true);
    }
}
